package cn.iocoder.yudao.module.resource.controller.admin.audiotone;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.infra.tts.ITTSApi;
import cn.iocoder.yudao.module.infra.tts.TTSServiceFactory;
import cn.iocoder.yudao.module.resource.controller.admin.audiotone.vo.AudioTonePageReqVO;
import cn.iocoder.yudao.module.resource.controller.admin.audiotone.vo.AudioToneRespVO;
import cn.iocoder.yudao.module.resource.controller.admin.audiotone.vo.AudioToneSaveReqVO;
import cn.iocoder.yudao.module.resource.dal.dataobject.audiotone.AudioToneDO;
import cn.iocoder.yudao.module.resource.service.audiotone.AudioToneService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Slf4j
@Tag(name = "管理后台 - 声纹管理")
@RestController
@RequestMapping("/resource/audio-tone")
@Validated
public class AudioToneController {

    @Resource
    private AudioToneService audioToneService;
    @Resource
    private FileApi fileApi;
    @Resource
    private TTSServiceFactory ttsServiceFactory;

    @GetMapping("/add-clone-voice-id")
    @Operation(summary = "添加音色复刻id")
    @PreAuthorize("@ss.hasPermission('resource:audio-tone:update')")
    public CommonResult<Boolean> addCloneVoiceId(@RequestParam("ttsName") String ttsName) {
        final ITTSApi ttsApi = ttsServiceFactory.getService(ttsName);

        final AudioTonePageReqVO req = new AudioTonePageReqVO();
        req.setPageNo(1);
        req.setPageSize(100);
        final PageResult<AudioToneDO> audioToneList = audioToneService.getAudioTonePage(req);

        for (AudioToneDO tone : audioToneList.getList()) {
            try {
                if (tone.getCloneVoiceObj() == null) {
                    tone.setCloneVoiceObj(new AudioToneDO.CloneVoice());
                }
                if (tone.getCloneVoiceObj().getTtsNameCloneVoiceIdMap() == null) {
                    tone.getCloneVoiceObj().setTtsNameCloneVoiceIdMap(new HashMap<>());
                }

                String cloneVoiceId = tone.getCloneVoiceObj().getTtsNameCloneVoiceIdMap().get(ttsName);
                if (StrUtil.isEmpty(cloneVoiceId)) {
                    final String url = fileApi.getTempDownloadUrlById(tone.getFileId(), null);
                    cloneVoiceId = ttsApi.createCloneVoice(url);
                    tone.getCloneVoiceObj().getTtsNameCloneVoiceIdMap().put(ttsName, cloneVoiceId);
                    log.info("创建音色, toneId = {}, cloneVoiceId = {}", tone.getId(), cloneVoiceId);
                }

                final String primaryName = ttsServiceFactory.getPrimaryName();
                final String primaryCloneVoiceId = tone.getCloneVoiceObj().getTtsNameCloneVoiceIdMap().get(primaryName);
                if (StrUtil.isEmpty(primaryCloneVoiceId)) {
                    tone.getCloneVoiceObj().getTtsNameCloneVoiceIdMap().put(primaryName, tone.getCloneVoiceId());
                    log.info("put音色到obj, toneId = {}, primaryName = {}, primaryCloneVoiceId = {}",
                            tone.getId(), primaryName, tone.getCloneVoiceId());
                }

                audioToneService.updateAudioToneById(tone);
            } catch (Exception e) {
                log.error(StrUtil.format("创建音色异常, toneId = {}", tone.getId()), e);
            }
        }

        return success(true);
    }

    @PostMapping("/create")
    @Operation(summary = "创建声纹管理")
    @PreAuthorize("@ss.hasPermission('resource:audio-tone:create')")
    public CommonResult<Integer> createAudioTone(@Valid @RequestBody AudioToneSaveReqVO createReqVO) {
        return success(audioToneService.createAudioTone(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新声纹管理")
    @PreAuthorize("@ss.hasPermission('resource:audio-tone:update')")
    public CommonResult<Boolean> updateAudioTone(@Valid @RequestBody AudioToneSaveReqVO updateReqVO) {
        audioToneService.updateAudioTone(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除声纹管理")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('resource:audio-tone:delete')")
    public CommonResult<Boolean> deleteAudioTone(@RequestParam("id") Integer id) {
        audioToneService.deleteAudioTone(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得声纹管理")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('resource:audio-tone:query')")
    public CommonResult<AudioToneRespVO> getAudioTone(@RequestParam("id") Integer id) {
        AudioToneDO audioTone = audioToneService.getAudioTone(id);
        AudioToneRespVO toneRespVO = BeanUtils.toBean(audioTone, AudioToneRespVO.class);
        audioToneService.setFileUrl(toneRespVO);
        return success(toneRespVO);
    }


    @GetMapping("/page")
    @Operation(summary = "获得声纹管理分页")
    @PreAuthorize("@ss.hasPermission('resource:audio-tone:query')")
    public CommonResult<PageResult<AudioToneRespVO>> getAudioTonePage(@Valid AudioTonePageReqVO pageReqVO) {
        PageResult<AudioToneDO> pageResult = audioToneService.getAudioTonePage(pageReqVO);
        PageResult<AudioToneRespVO> voPageResult = BeanUtils.toBean(pageResult, AudioToneRespVO.class);
        voPageResult.getList().forEach(c -> audioToneService.setFileUrl(c));
        return success(voPageResult);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出声纹管理 Excel")
    @PreAuthorize("@ss.hasPermission('resource:audio-tone:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportAudioToneExcel(@Valid AudioTonePageReqVO pageReqVO,
                                     HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<AudioToneDO> list = audioToneService.getAudioTonePage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "声纹管理.xls", "数据", AudioToneRespVO.class,
                BeanUtils.toBean(list, AudioToneRespVO.class));
    }

}